/**
 * @Description： The implemented class for interface IRoleService
 * @author： YouYu 游宇
 * @createTime: 2018-12-04 7:27 PM
 **/

package com.scb.dev.mms.service.impl;

import com.scb.dev.mms.common.DataCommon;
import com.scb.dev.mms.common.ResponseResult;
import com.scb.dev.mms.common.StatusCode;
import com.scb.dev.mms.dao.*;
import com.scb.dev.mms.feign.EmployeeFeign;
import com.scb.dev.mms.pojo.RmoGrant;
import com.scb.dev.mms.pojo.Role;
import com.scb.dev.mms.pojo.RoleGroup;
import com.scb.dev.mms.request.RoleVORequest;
import com.scb.dev.mms.service.IRoleService;
import com.scb.dev.mms.util.DateTool;
import com.scb.dev.mms.util.ListUtil;
import com.scb.dev.mms.util.UUIDTool;
import com.scb.dev.mms.vo.MenuVO;
import com.scb.dev.mms.vo.OperationVO;
import com.scb.dev.mms.vo.RoleVO;
import feign.Feign;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import java.util.*;

/**
 * @className: RoleServiceImpl
 * @Description: The implemented class for interface IRoleService
 * @author: YouYu 游宇
 * @createTime: 2018-12-04 7:27 PM
 **/
@Slf4j
@Service
public class RoleServiceImpl implements IRoleService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RmoGrantMapper rmoGrantMapper;
    /*
    @Autowired
    private RoleGroupMapper roleGroupMapper;
    */
    @Autowired
    private MenuMapper menuMapper;
    @Autowired
    private OperationMapper operationMapper;
    @Autowired
    private EmployeeFeign employeeFeign;

    @Transactional
    @Override
    public ResponseResult queryRoleInfoByRoleId(String roleId) {
       ResponseResult responseResult= new ResponseResult();
       RoleVO roleVO=new RoleVO();
       RoleGroup roleGroup=null;
       List<String> menuIdList=null;
       List<String> operationIdList=null;
       List menuTree;
       try{
           Role role=roleMapper.selectByPrimaryKey(roleId);
           log.info("roleServiceImpl role=="+role);
           menuIdList=rmoGrantMapper.selectMenuIdByRoleId(roleId);
           operationIdList=rmoGrantMapper.selectOperationIdsByRoleId(roleId);
           /*if(role.getRoleGroupId()!=null&role.getRoleGroupId()!=""){
               roleGroup= roleGroupMapper.selectByPrimaryKey(role.getRoleGroupId());
           }*/
           List<MenuVO> menuVOList=new ArrayList<>();
           for (int i=0;i<menuIdList.size();i++) {
               MenuVO menuVO=new MenuVO();
               menuVO.setMenu(menuMapper.selectByMenuId(menuIdList.get(i)));
               menuVO.setMenuCreatorAccountName("");
               menuVO.setMenuUpdatorAccountName("");
               log.info("menuVO=="+menuVO);
               menuVOList.add(menuVO);
           }

           List<OperationVO> operationVOList=new ArrayList<>();
           for (int i=0;i<operationIdList.size();i++) {
               OperationVO operationVO=new OperationVO();
               operationVO.setOperation(operationMapper.selectByPrimaryKey(operationIdList.get(i)));
               operationVO.setOperationCreatorAccountName("");
               operationVO.setOperationUpdatorAccountName("");
               operationVOList.add(operationVO);
           }
           log.info("role=="+role);
           log.info("menuVOList=="+menuVOList);
           log.info("operationVOList=="+operationVOList);
           roleVO.setRole(role);
           roleVO.setMenuList(menuVOList);
           roleVO.setOperationList(operationVOList);
           //roleVO.setRoleGroup(roleGroup);
           roleVO.setRoleCreatorAccountName("");
           roleVO.setRoleUpdatorAccountName("");

           responseResult=ResponseResult.responseResult(roleVO,true,"queryRoleByRoleId success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
       }catch(NullPointerException e){
           responseResult=ResponseResult.responseResult(roleVO,false,"queryRoleByRoleId failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
           e.printStackTrace();
       }catch (Exception e){
           responseResult=ResponseResult.responseResult(roleVO,false,"queryRoleByRoleId failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
           e.printStackTrace();
       }
       return responseResult;
    }

    @Override
    public ResponseResult queryAllRole() {
        ResponseResult responseResult=new ResponseResult();
        List<RoleVO> roleVOList=new ArrayList<>();
        try{
            List<Role> roleList=roleMapper.selectAllRole();
            for (Role role: roleList) {
                RoleVO roleVO=new RoleVO();
                roleVO.setRole(role);
                roleVO.setCreateTime(DateTool.dateToString(role.getRoleCreatedTime(),DataCommon.YYYY_1MM_1DD_HH_MM_SS));
                if(role.getRoleUpdatedTime()!=null){
                    roleVO.setUpdatedTime(DateTool.dateToString(role.getRoleUpdatedTime(),DataCommon.YYYY_1MM_1DD_HH_MM_SS));
                }else{
                    roleVO.setUpdatedTime("暂未更新!");
                }
                roleVOList.add(roleVO);
            }
            log.info("authority  queryAllRole success!");
            responseResult=ResponseResult.responseResult(roleVOList,true,"queryAllRole success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
        }catch (NullPointerException e){
            log.info("authority  NullPointException");
            responseResult=ResponseResult.responseResult(roleVOList,false,"queryAllRole failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }catch (Exception e){
            log.info("authority  Exception");
            responseResult=ResponseResult.responseResult(roleVOList,false,"queryAllRole failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }
        return responseResult;
    }

    @Override
    public ResponseResult queryRoleNameByRoleId(String roleId) {
        ResponseResult responseResult=new ResponseResult();
        String roleName=null;
        try{
            roleName=roleMapper.selectRoleNameByRoleId(roleId);
            responseResult=ResponseResult.responseResult(roleName,true,"queryRoleNameByRoleId success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
        }catch (NullPointerException e){
            responseResult=ResponseResult.responseResult(roleName,false,"queryRoleNameByRoleId failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }catch (Exception e){
            responseResult=ResponseResult.responseResult(roleName,false,"queryRoleNameByRoleId failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }
        return responseResult;
    }

    @Transactional
    @Override
    public ResponseResult addRole(RoleVORequest roleVORequest) {
        boolean rollbackFlag=DataCommon.ROLLBACK_FALSE;
        ResponseResult responseResult=new ResponseResult();
        try{
            Role role=roleMapper.selectRoleByRoleName(roleVORequest.getRoleName());
            if(role==null){
                List<String> menuIdListGet=roleVORequest.getMenuIdList();
                List<String> roleIdList=rmoGrantMapper.selectRoleIdGroupByRoleId();
                for (String roleId:roleIdList) {
                    List<String> menuIdList =rmoGrantMapper.selectMenuIdByRoleId(roleId);
                    boolean flag=ListUtil.isListEqual(menuIdList,menuIdListGet);
                    if(flag){
                        log.info("there is already a role has the same right");
                        responseResult=ResponseResult.responseResult(false,false,"add Role failed! There is already a role which has the same right!", StatusCode.ADDERROR, DataCommon.ICON_ERROR);
                        return responseResult;
                    }
                }
                Role roleToAdd=new Role();
                roleToAdd.setRoleId(UUIDTool.generateUUID());
                roleToAdd.setRoleName(roleVORequest.getRoleName());
                roleToAdd.setRoleGroupId(roleVORequest.getRoleGroupId());
                roleToAdd.setRoleRemarks(roleVORequest.getRoleRemarks());
                roleToAdd.setRoleCreatorAccountId(roleVORequest.getRoleCreatorAccountId());
                roleToAdd.setRoleCreatedTime(DateTool.getTimeStamp());
                roleMapper.insertSelective(roleToAdd);

                for (int i=0;i<menuIdListGet.size();i++ ) {
                    RmoGrant  rmoGrant=new RmoGrant();
                    rmoGrant.setRmoGrantId(UUIDTool.generateUUID());
                    rmoGrant.setRmoGrantRoleId(roleToAdd.getRoleId());
                    rmoGrant.setRmoGrantMenuId(menuIdListGet.get(i));
                    rmoGrant.setRmoGrantOperationId(null);
                    rmoGrant.setRmoGrantCreatedTime(DateTool.getTimeStamp());
                    rmoGrant.setRmoGrantCreatorId(roleToAdd.getRoleCreatorAccountId());
                    rmoGrantMapper.insertSelective(rmoGrant);
                }
                responseResult=ResponseResult.responseResult(true,true,"add Role success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);

            }else{
                log.info("same name");
                rollbackFlag=DataCommon.ROLLBACK_TRUE;
                responseResult=ResponseResult.responseResult(false,false,"add Role failed!, there is already a role name so", StatusCode.ADDERROR, DataCommon.ICON_ERROR);
            }
        }catch (NullPointerException e){
            log.error("add role failed NullPointerException");
            rollbackFlag=DataCommon.ROLLBACK_TRUE;
            e.printStackTrace();
            responseResult=ResponseResult.responseResult(false,false,"add Role failed! NullPointerException!", StatusCode.ADDERROR, DataCommon.ICON_ERROR);
        }catch (Exception e){
            log.error("add role failed unexpected Exception");
            rollbackFlag=DataCommon.ROLLBACK_TRUE;
            e.printStackTrace();
            responseResult=ResponseResult.responseResult(false,false,"add Role failed! unexpected Exception!", StatusCode.ADDERROR, DataCommon.ICON_ERROR);
        }finally {
            if (rollbackFlag){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // rollback the transaction manually
            }
        }
        return responseResult;
    }


    @Override
    public ResponseResult queryAllRoleName() {
        ResponseResult responseResult=new ResponseResult();
        Map<String,String> roleNameMap=new HashMap<>();
        try{
            List<Role> roleList=roleMapper.selectAllRole();
            for (int i=0;i<roleList.size();i++){
                roleNameMap.put(roleList.get(i).getRoleName(),roleList.get(i).getRoleId());
            }
            responseResult=ResponseResult.responseResult(roleNameMap,true,"queryAllRoleName success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
            log.info("queryAllRoleName success!");
        }catch (Exception e){
            log.info("queryAllRoleName fail!");
            responseResult=ResponseResult.responseResult(roleNameMap,false,"queryAllRoleName failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }
        return responseResult;
    }

    @Override
    public ResponseResult queryMenusByRoleId(String roleId) {
        ResponseResult responseResult=new ResponseResult();
        List<String> menuIdList=new ArrayList<>();
        try {
            menuIdList=rmoGrantMapper.selectMenuIdByRoleId(roleId);
            responseResult=ResponseResult.responseResult(menuIdList,true,"queryMenuByRoleId success!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_ERROR);
        }catch (NullPointerException e){
            responseResult=ResponseResult.responseResult(menuIdList,false,"queryMenuByRoleId failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }catch (Exception e){
            responseResult=ResponseResult.responseResult(menuIdList,false,"queryMenuByRoleId failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }
        return responseResult;
    }

    @Override
    public ResponseResult queryRoleByRoleName(String roleName) {
        ResponseResult responseResult=new ResponseResult();
        Role role=new Role();
        try{
            role=roleMapper.selectRoleByRoleName(roleName);
            if(role==null){
                responseResult=ResponseResult.responseResult(role,true,"there is no role like this name!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
            }else{
                responseResult=ResponseResult.responseResult(role,true,"there is a role already!", StatusCode.OPERATIONSUCCESS, DataCommon.ICON_SUCCESS);
            }
        }catch (NullPointerException e){
            responseResult=ResponseResult.responseResult(role,false,"queryMenuByRoleId failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }catch (Exception e){
            responseResult=ResponseResult.responseResult(role,false,"queryMenuByRoleId failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }
        return responseResult;
    }

    @Transactional
    @Override
    public ResponseResult deleteRole(String roleId) {
        ResponseResult responseResult=new ResponseResult();
        boolean rollbackFlag=DataCommon.ROLLBACK_FALSE;
        try {
            //the first step:select role and delete role
            Role role=roleMapper.selectByPrimaryKey(roleId);
            if(role==null){
                responseResult=ResponseResult.responseResult(false,false,"delete role failed! Can't find the role!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
                return responseResult;
            }else{
                roleMapper.deleteByPrimaryKey(roleId);
                //the second step:delete the record of right for the role
                int menuNum=rmoGrantMapper.selectByRoleId(roleId);
                boolean flag1=false;
                if(menuNum>0){
                    flag1=rmoGrantMapper.deleteByRoleId(roleId);
                    if(!flag1){
                        rollbackFlag=DataCommon.ROLLBACK_TRUE;
                    }
                }
                //the third step: update all the employee's roleId with a default roleId,
                ResponseResult responseResult1=employeeFeign.setDefaultRoleId(roleId);
                if(!responseResult1.isSuccess()){
                    rollbackFlag=false;
                    responseResult=ResponseResult.responseResult(responseResult1.getData(),false,responseResult1.getMessage(), responseResult1.getCode(), DataCommon.ICON_ERROR);
                }
                responseResult=ResponseResult.responseResult(true,true,"deleteRole success!", StatusCode.ADDSUCCESS, DataCommon.ICON_SUCCESS);
            }
        }catch (NullPointerException e){
            responseResult=ResponseResult.responseResult(false,false,"delete role failed! NullPointException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }catch (Exception e){
            responseResult=ResponseResult.responseResult(false,false,"delete role failed! Unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
            e.printStackTrace();
        }finally{
            if (rollbackFlag){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // rollback the transaction manually
                log.info("failed to delete role with error,transaction rollback finished!");
            }
        }
        return responseResult;
    }


    @Override
    public ResponseResult updateRole(RoleVORequest roleVORequest) {
        boolean rollbackFlag=DataCommon.ROLLBACK_FALSE;
        ResponseResult responseResult=new ResponseResult();
        try{
            Role role=roleMapper.selectByPrimaryKey(roleVORequest.getRoleId());
            if(role!=null){
                List<String> menuIdListGet=roleVORequest.getMenuIdList();
                List<String> roleIdList=rmoGrantMapper.selectRoleIdGroupByRoleId();
                for (String roleId:roleIdList) {
                    List<String> menuIdList =rmoGrantMapper.selectMenuIdByRoleId(roleId);
                    boolean flag=ListUtil.isListEqual(menuIdList,menuIdListGet);
                    if(flag){
                        log.info("there is already a role has the same right");
                        responseResult=ResponseResult.responseResult(false,false,"update Role failed! There is already a role which has the same right!", StatusCode.UPDATEERROR, DataCommon.ICON_ERROR);
                        return responseResult;
                    }
                }
                Role roleToUpdate=new Role();
                roleToUpdate.setRoleId(UUIDTool.generateUUID());
                roleToUpdate.setRoleName(roleVORequest.getRoleName());
                roleToUpdate.setRoleGroupId(roleVORequest.getRoleGroupId());
                roleToUpdate.setRoleRemarks(roleVORequest.getRoleRemarks());
                roleToUpdate.setRoleUpdatorAccountId(roleVORequest.getRoleUpdatorAccountId());
                roleToUpdate.setRoleUpdatedTime(DateTool.getTimeStamp());
                roleMapper.updateByPrimaryKeySelective(roleToUpdate);

                List menuIdList=rmoGrantMapper.selectMenuIdByRoleId(roleVORequest.getRoleId());
                if(menuIdList!=null){
                    rmoGrantMapper.deleteByRoleId(roleVORequest.getRoleId());
                }
                for (int i=0;i<menuIdListGet.size();i++ ) {
                    RmoGrant  rmoGrant=new RmoGrant();
                    rmoGrant.setRmoGrantId(UUIDTool.generateUUID());
                    rmoGrant.setRmoGrantRoleId(roleToUpdate.getRoleId());
                    rmoGrant.setRmoGrantMenuId(menuIdListGet.get(i));
                    rmoGrant.setRmoGrantOperationId(null);
                    rmoGrant.setRmoGrantCreatedTime(DateTool.getTimeStamp());
                    rmoGrant.setRmoGrantCreatorId(role.getRoleCreatorAccountId());
                    rmoGrantMapper.insertSelective(rmoGrant);
                }
                responseResult=ResponseResult.responseResult(true,true,"update Role success!", StatusCode.UPDATESUCCESS, DataCommon.ICON_SUCCESS);
            }else{
                log.info("There is no such role!");
                responseResult=ResponseResult.responseResult(false,false,"update Role failed!, there is no a role named so", StatusCode.UPDATEERROR, DataCommon.ICON_ERROR);
            }
        }catch (NullPointerException e){
            log.error("add role failed NullPointerException");
            rollbackFlag=DataCommon.ROLLBACK_TRUE;
            e.printStackTrace();
            responseResult=ResponseResult.responseResult(false,false,"update Role failed! NullPointerException!", StatusCode.FINDNULL, DataCommon.ICON_ERROR);
        }catch (Exception e){
            log.error("add role failed unexpected Exception");
            rollbackFlag=DataCommon.ROLLBACK_TRUE;
            e.printStackTrace();
            responseResult=ResponseResult.responseResult(false,false,"update Role failed! unexpected Exception!", StatusCode.EXCEPTIONERROR, DataCommon.ICON_ERROR);
        }finally {
            if (rollbackFlag){
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); // rollback the transaction manually
            }
        }
        return responseResult;
    }
}
